home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / utilit~1 / akputil7.zoo / mv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-13  |  5.8 KB  |  237 lines

  1. #include <minimal.h>
  2. #include <osbind.h>
  3. #include <string.h>
  4.  
  5. #define EACCDN -36
  6. #define ENSAME -48
  7.  
  8. #define TRUE 1
  9. #define FALSE 0
  10.  
  11. #define NULL 0
  12. #define FILENAME_MAX 128
  13.  
  14. extern char *syserr(long);
  15.  
  16. #define DIRSEP(c) (((c) == '\\') || ((c) == '/'))
  17.  
  18. int
  19. do_mv(char *src,char *dest,int destisdir,int force) {
  20.     long size, rsize, wsize;
  21.     int srcfd = 0, destfd = 0;
  22.     char *buf = NULL;
  23.     long bsize;
  24.     char *e, *efile;
  25.     long err;
  26.     char attr;
  27.     int datime[2];
  28.     char destname[FILENAME_MAX], *d;
  29.     char *s, *srcname;
  30.     int firstflag;
  31.  
  32.     /*
  33.      * if the dest is a directory:
  34.      *    put a backslash on the end if there isn't one there already,
  35.      *  set srcname past the last path separator in src (or src itself),
  36.      *    copy the last component of src after the trailing backslash,
  37.      *    set dest to this constructed filename.
  38.      */
  39.  
  40.     if (destisdir) {
  41.     strcpy(destname,dest);
  42.     for (d = destname; *d; d++) ;
  43.     if (!DIRSEP(*(d-1))) *d++ = '\\';
  44.     for (srcname = s = src; *s; s++) {
  45.         if (DIRSEP(*s)) srcname = s+1;
  46.     }
  47.     strcpy(d,srcname);
  48.     dest = destname;
  49.     }
  50.  
  51.     efile = src;
  52.  
  53.     /* try an actual rename first, in case it works! */
  54.     if ((err = Frename(0,src,dest)) == 0) return 0;
  55.     else if (err == EACCDN) {
  56.         /* access denied - maybe an existing file by that name */
  57.         if (err = Fdelete(dest)) {
  58.             /* can't delete */
  59.             if (force) {
  60.             if (err = Fattrib(dest,1,0)) goto error;
  61.             if (err = Fdelete(dest)) goto error;
  62.             if (err = Frename(0,src,dest)) goto error;
  63.             return 0;
  64.             }
  65.             else goto error;
  66.         }
  67.     /* delete succeeded */
  68.         if (err = Frename(0,src,dest)) goto error;
  69.         else return 0;
  70.     }
  71.     else if (err != ENSAME) goto error;
  72.  
  73.     /* OK, rename didn't work (ENSAME), try copying then deleting */
  74.     if ((err = srcfd = Fopen(src,0)) < 0) goto error;
  75.     if ((err = attr = Fattrib(src,0,0)) < 0) goto error;
  76.     if ((err = size = Fseek(0L,srcfd,2)) < 0) goto error;
  77.     if (err = Fseek(0L,srcfd,0)) goto error;
  78.     if (err = Fdatime(datime,srcfd,0)) goto error;
  79.  
  80.     bsize = size;
  81.     do {
  82.     if (buf = (char *)Malloc(bsize)) break;
  83.     bsize /= 2;
  84.     } while (bsize >= 512);
  85.  
  86.     if (buf == NULL) {
  87.     e = "no memory";
  88.     goto error1;
  89.     }
  90.  
  91.     /* We play games with firstflag so the dest file isn't created     */
  92.     /* until the source file has been opened, the memory allocated, and    */
  93.     /* the first buffer-full has actually been read.            */
  94.  
  95.     firstflag = 1;
  96.     while (1) {
  97.     efile = src;
  98.  
  99.     if ((err = rsize = Fread(srcfd,bsize,buf)) < 0) goto error;
  100.  
  101.     efile = dest;
  102.  
  103.     if (firstflag) {
  104.         if ((err = destfd = Fcreate(dest,0)) < 0) goto error;
  105.         firstflag = 0;
  106.     }
  107.  
  108.     /* rsize == 0 if we're done. */
  109.     /* File might be empty so break after creating dest. */
  110.     if (rsize == 0) break;
  111.  
  112.     if ((err = wsize = Fwrite(destfd,rsize,buf)) < 0) goto error;
  113.     else if (wsize != rsize) {
  114.         e = "write error (disk full?)";
  115.         goto error1;
  116.     }
  117.     }
  118.  
  119.     efile = dest;
  120.     if (err = Fdatime(datime,destfd,1)) goto error;
  121.     if (err = Fclose(destfd)) goto error;
  122.     destfd = 0;
  123.     if ((err = Fattrib(dest,1,attr)) < 0) goto error;
  124.     efile = src;
  125.     if (err = Fclose(srcfd)) goto error;
  126.     srcfd = 0;
  127.  
  128.     /* Copy complete, now delete the original. */
  129.     /* If "force" then override a read-only file before deleting. */
  130.     if (attr & 1) {
  131.     if ((err = Fattrib(src,1,0)) < 0) goto err2;
  132.     }
  133.     if ((err = Fdelete(src)) < 0) goto err2;
  134.  
  135.     (void)Mfree(buf);
  136.     return 0;
  137.  
  138. err2:
  139.     (void)Fwrite(2,13L,"Can't delete ");
  140. error:
  141.     e = syserr(err);
  142. error1:
  143.     (void)Fwrite(2,(long)strlen(efile),efile);
  144.     (void)Fwrite(2,2L,": ");
  145.     (void)Fwrite(2,(long)strlen(e),e);
  146.     (void)Fwrite(2,2L,"\r\n");
  147.     if (srcfd > 0) (void)Fclose(srcfd);
  148.     if (destfd > 0) {
  149.     (void)Fclose(destfd);
  150.     (void)Fdelete(dest);
  151.     }
  152.     if (buf) (void)Mfree(buf);
  153.     return 1;
  154. }
  155.  
  156. #define haswild(s) (strchr(s,'*') || strchr(s,'?'))
  157.  
  158. int
  159. main(int argc,char *argv[])
  160. {
  161.     char *p;
  162.     int e;
  163.     int destisdir;
  164.     char *s, *lastcomp;
  165.     int fflag = 0;
  166.  
  167.     --argc, ++argv;
  168.     while (*argv && **argv == '-') {
  169.         p = &argv[0][1];
  170.         while (*p) {
  171.         switch (*p) {
  172.             case 'f': fflag = 1; break;
  173.         default:
  174.             (void)Fwrite(2,15L,"Unknown option:");
  175.             (void)Fwrite(2,1L,p);
  176.             (void)Fwrite(2,2L,"\r\n");
  177.             goto usage;
  178.         }
  179.         p++;
  180.     }
  181.     argc--, argv++;
  182.     }
  183.  
  184.     if (argc < 2) {
  185. usage:
  186.     (void)Fwrite(2,25L,"Usage: mv [-f] src dest\r\n");
  187.     (void)Fwrite(2,37L,"   or: mv [-f] srcfiles ... destdir\r\n");
  188.     (void)Fwrite(2,35L,"-f means remove dest if it exists\r\n");
  189.     Pterm(1);
  190.     }
  191.  
  192.     /* set p to point to the last arg; see if it's a directory */
  193.     p = argv[argc-1];
  194.     destisdir = 0;
  195.  
  196.     /* dest is a dir if the name is two letters long & ends with ':' */
  197.     if (*p && *(p+1) == ':' && !*(p+2)) {
  198.     destisdir = 1;
  199.     goto gotdir;
  200.     }
  201.  
  202.     for (lastcomp = s = p; *s; s++) {
  203.     if (DIRSEP(*s)) lastcomp = s+1;
  204.     }
  205.  
  206.     /* dot and dot-dot are directories (trust me), and if   */
  207.     /* the name ends with a DIRSEP it's a directory too.    */
  208.     /* Also if the name is two chars long & ends with a colon. */
  209.  
  210.     if (!*lastcomp || 
  211.     (*lastcomp == '.' && 
  212.         (*(lastcomp+1) == '.' || (*(lastcomp+1)) == '\0'))) {
  213.     destisdir = 1;
  214.     }
  215.     else if (!haswild(p) && (Fsfirst(p,-1) == 0)) {
  216.     destisdir = ((struct _dta *)Fgetdta())->dta_attribute & 0x10;
  217.     }
  218.  
  219. gotdir:
  220.     if (argc == 2) {
  221.     return do_mv(argv[0],argv[1],destisdir,fflag);
  222.     }
  223.  
  224.     if (!destisdir) {
  225.     (void)Fwrite(2,30L,"last arg must be a directory\r\n");
  226.     Pterm(1);
  227.     }
  228.  
  229.     e = 0;
  230.     while (argc > 1) {
  231.     e |= do_mv(*argv,p,1,fflag);
  232.     argv++, argc--;
  233.     }
  234.     return (e != 0);
  235. }
  236.  
  237.